﻿using LJ.FaultHandler.Abstractions;
using Polly.Retry;
using Polly;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LJ.Abstractions.Extensions;
using System.Collections.Immutable;
using System.Net.Sockets;
using LJ.Abstractions.Exceptions;

namespace LJ.FaultHandler.Polly.Internal;

public class PollyFaultHandler(IServiceProvider serviceProvider) : IFaultHandler
{
    private readonly RetryStrategyOptions _retryStrategyOptions = new()
    {
        BackoffType = DelayBackoffType.Exponential,
        UseJitter = false,
        MaxRetryAttempts = 2,
        Delay = TimeSpan.FromSeconds(1),
        ShouldHandle = args => ValueTask.FromResult(args.Outcome.Exception is not AppException && args.Outcome.Exception is not FriendlyException)

    };

    private readonly PollyFaultHandlerConfig faultHandlerConfig = serviceProvider.GetConfig<PollyFaultHandlerConfig>();
    public void SetAppKey(string key)
    {
        var config = faultHandlerConfig.Infos.Where(a => a.Key == key).FirstOrDefault();
        if (config != null)
        {
            _retryStrategyOptions.MaxRetryAttempts = config.MaxRetryAttempt;
            _retryStrategyOptions.Delay = TimeSpan.FromSeconds(config.Delay);
        }
    }



    public async Task<T> ExecuteAsync<T>(Func<CancellationToken, Task<T>> callback, CancellationToken cancellationToken)
    {
        var pipeline = new ResiliencePipelineBuilder().AddRetry(_retryStrategyOptions).Build();
        return await pipeline.ExecuteAsync(async token =>
        {
            return await callback(token);
        }, cancellationToken);
    }
    public async Task ExecuteAsync(Func<CancellationToken, Task> callback, CancellationToken cancellationToken)
    {
        var pipeline = new ResiliencePipelineBuilder().AddRetry(_retryStrategyOptions).Build();
        await pipeline.ExecuteAsync(async token =>
        {
            await callback(token);
        }, cancellationToken);
    }
}
